/**************************************************************************
 * Copyright (C) 2012 Marcin Kunicki <masel.popowo@gmail.com>
 * $LastChangedRevision: 87 $
 * $LastChangedBy: masel.popowo@gmail.com $
 * $LastChangedDate: 2012-12-14 09:42:47 +0000 (Fri, 14 Dec 2012) $
 * $HeadURL: http://pps-addressbook.googlecode.com/svn/branches/unitsListFilterFunction/src/org/ewicom/ppsaddressbook/UnitsList.java $
 *
 * This file is part of PPS-AddressBook.
 *
 * PPS-AddressBook is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * PPS-AddressBook is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PPS-AddressBook; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Ten plik jest częścią PPS-AddressBook.
 * 
 * PPS-AddressBook jest wolnym oprogramowaniem; możesz go rozprowadzać dalej
 * i/lub modyfikować na warunkach Powszechnej Licencji Publicznej GNU,
 * wydanej przez Fundację Wolnego Oprogramowania - według wersji 2 tej
 * Licencji lub (według twojego wyboru) którejś z późniejszych wersji.
 * 
 * Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on
 * użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej
 * gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH
 * ZASTOSOWAŃ. W celu uzyskania bliższych informacji sięgnij do
 * Powszechnej Licencji Publicznej GNU.
 * 
 * Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz
 * Powszechnej Licencji Publicznej GNU (GNU General Public License);
 * jeśli nie - napisz do Free Software Foundation, Inc., 59 Temple
 * Place, Fifth Floor, Boston, MA  02110-1301  USA
 **************************************************************************/
package org.ewicom.ppsaddressbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.ewicom.ppsaddressbook.PPSAddressBook.PPSAddressBookPreferences;
import org.ewicom.ppsaddressbook.model.ReleaseInfo;
import org.ewicom.ppsaddressbook.model.Unit;
import org.ewicom.ppsaddressbook.model.UnitDataSource;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;

public class UnitsList extends ListActivity {

	private static final String TAG = "UnitsList";

	private UnitDataSource unitDataSource;
	
	private ReleaseInfo stableRelease;
	private ReleaseInfo testingRelease;
	
	private TextWatcher searchTextWatcher;
	private EditText searchEditText;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.unitslist_searchview);
		
		
		final Intent intent = getIntent();
		
		stableRelease = (ReleaseInfo) intent.getParcelableExtra(PPSAddressBookPreferences.INTENT_EXTRA_RELEASE_STABLE);
		testingRelease = (ReleaseInfo) intent.getParcelableExtra(PPSAddressBookPreferences.INTENT_EXTRA_RELEASE_TESTING);

		unitDataSource = new UnitDataSource(this);
		unitDataSource.open();

		List<Unit> units = unitDataSource.getAllUnits();

		final UnitListAdapter adapter = new UnitListAdapter(this, units);
		setListAdapter(adapter);
		
		if(stableRelease != null){
			Log.v(TAG, "Jest stablilna aktualizacja: " + stableRelease.getVersionName());
			showAppUpdateDialog(stableRelease);
		}
		
		searchTextWatcher = new TextWatcher() {
			
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
			
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}
			
			@Override
			public void afterTextChanged(Editable s) {
				Log.d("WYSZUKIWANIE: ", s.toString());
				adapter.getFilter().filter(s);
			}
		};
		
		searchEditText = (EditText) findViewById(R.id.unitslist_searchbox);
		searchEditText.addTextChangedListener(searchTextWatcher);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.mainmenu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_about:
			showAboutDialog();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		Intent intent = new Intent();
		intent.setClass(this, UnitDetails.class);
		intent.putExtra(PPSAddressBookPreferences.INTENT_EXTRA_UNIT_ID, id);
		startActivity(intent);
	}

	@Override
	protected void onResume() {
		unitDataSource.open();
		super.onResume();
	}

	@Override
	protected void onPause() {
		unitDataSource.close();
		super.onPause();
	}

	public void showAboutDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		LayoutInflater inflater = this.getLayoutInflater();
		View view = inflater.inflate(R.layout.dialog_about, null);
		TextView appVersionTV = (TextView) view.findViewById(R.id.dialog_about_appversion);
		TextView databaseVersionTV = (TextView) view
				.findViewById(R.id.dialog_about_appdatabase);
		TextView unitCountTV = (TextView) view.findViewById(R.id.dialog_about_appcount);

		appVersionTV.setText("VERSION: "
				+ PPSAddressBook.getAppVersionName(this));

		SharedPreferences settings = getSharedPreferences(
				PPSAddressBookPreferences.PREFERENCES_FILE, MODE_PRIVATE);
		databaseVersionTV
				.setText("DATABASE: "
						+ settings
								.getString(
										PPSAddressBookPreferences.PREFERENCE_KEY_DATABASE_VERSION,
										"NO_VERSION"));

		unitCountTV.setText("COUNT: " + unitDataSource.getCountOfUnits());
		
		builder.setTitle(R.string.menu_about)
		.setIcon(R.drawable.ic_action_about)
		.setView(view)
		.setNeutralButton(R.string.button_ok,
				new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog,
							int which) {
					}
				});
		final AlertDialog aboutDialog = builder.create();
		
		Button stableReleaseInstallBtn = (Button) view.findViewById(R.id.dialog_about_srelease_install_btn);
		stableReleaseInstallBtn.setVisibility(View.INVISIBLE);
		if(stableRelease != null){
			stableReleaseInstallBtn.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					aboutDialog.dismiss();
					showAppUpdateDialog(stableRelease);
				}
			});
			stableReleaseInstallBtn.setText(getResources().getString(R.string.button_install_stable_release, stableRelease.getVersionName()));
			stableReleaseInstallBtn.setVisibility(View.VISIBLE);
			Log.v(TAG, "Jest stablilna aktualizacja: " + stableRelease.getVersionName());
		}
		
		Button testingReleaseInstallBtn = (Button) view.findViewById(R.id.dialog_about_trelease_install_btn);
		testingReleaseInstallBtn.setVisibility(View.INVISIBLE);
		if(testingRelease != null){
			testingReleaseInstallBtn.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					aboutDialog.dismiss();
					showAppUpdateDialog(testingRelease);
				}
			});
			testingReleaseInstallBtn.setText(getResources().getString(R.string.button_install_testing_release, testingRelease.getVersionName()));
			testingReleaseInstallBtn.setVisibility(View.VISIBLE);
			Log.v(TAG, "Jest testowa aktualizacja: " + testingRelease.getVersionName());
		}

		aboutDialog.show();
	}

	public void showAppUpdateDialog(final ReleaseInfo release) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		LayoutInflater inflater = this.getLayoutInflater();
		View view = inflater.inflate(R.layout.dialog_update, null);
		
		TextView versionTV = (TextView) view.findViewById(R.id.dialog_update_version);
		TextView dateTV = (TextView) view.findViewById(R.id.dialog_update_date);
		TextView infoTV = (TextView) view.findViewById(R.id.dialog_update_info);
		
		versionTV.setText("VERSION: " + release.getVersionName());
		dateTV.setText(release.getReleaseDate());
		infoTV.setText(release.getChangelog());
	

		builder.setTitle(R.string.dialog_changelog_title)
				.setIcon(R.drawable.ic_action_help)
				.setView(view)
				.setPositiveButton(R.string.button_update,
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								new DownloadAppUpdateTask(UnitsList.this, release).execute();

							}
						})
				.setNegativeButton(R.string.button_cancel,
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
							}
						});

		builder.create().show();
	}

	private void installAppUpdate(File updateFile) {
		finish();
		Intent intent = new Intent(Intent.ACTION_VIEW);
		Uri uri = Uri.fromFile(updateFile);
		intent.setDataAndType(uri, "application/vnd.android.package-archive");
		startActivity(intent);
	}
	
	private class UnitListAdapter extends BaseAdapter implements Filterable {

		private List<Unit> units;
		private List<Unit> fullUnitsList;
		private Context mContext;
		private LayoutInflater inflator;
		
		public UnitListAdapter(Context context, List<Unit> units) {
			this.units = units;
			this.mContext = context;
			this.inflator = (LayoutInflater) mContext
					.getSystemService(LAYOUT_INFLATER_SERVICE);
		}

		@Override
		public int getCount() {
			return units.size();
		}

		@Override
		public Object getItem(int position) {
			return units.get(position);
		}

		@Override
		public long getItemId(int position) {
			return units.get(position).getId();
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			final MainListHolder mHolder;
			View v = convertView;
			if (convertView == null) {
				mHolder = new MainListHolder();
				v = inflator.inflate(R.layout.unitslist_item, null);
				mHolder.shortUnitName = (TextView) v
						.findViewById(R.id.shortUnitName);
				mHolder.longUnitName = (TextView) v
						.findViewById(R.id.longUnitName);
				v.setTag(mHolder);
			} else {
				mHolder = (MainListHolder) v.getTag();
			}

			mHolder.shortUnitName.setText(units.get(position).getShortName());
			String longName = units.get(position).getStreet() + ", "
					+ units.get(position).getCity();
			mHolder.longUnitName.setText(longName);

			return v;
		}

		private class MainListHolder {
			private TextView shortUnitName;
			private TextView longUnitName;
		}

		@Override
		public Filter getFilter() {
			return new Filter() {
				
				@SuppressWarnings("unchecked")
				@Override
				protected void publishResults(CharSequence constraint, FilterResults results) {
					units = (List<Unit>) results.values;
					UnitListAdapter.this.notifyDataSetChanged();
					
				}
				
				@Override
				protected FilterResults performFiltering(CharSequence constraint) {
					if(fullUnitsList == null){
						fullUnitsList = new ArrayList<Unit>(units);
					}
					
					List<Unit> filteredUnits = new ArrayList<Unit>(fullUnitsList);
					
					for(Iterator<Unit> it = filteredUnits.iterator();it.hasNext();){
						if(!it.next().getShortName().toLowerCase().startsWith(constraint.toString().toLowerCase())){
							it.remove();
						}
					}		
					
					FilterResults filterResults = new FilterResults();
					filterResults.values = filteredUnits;
					filterResults.count = filteredUnits.size();
					return filterResults;
				}
			};
		}

	}

	private class DownloadAppUpdateTask extends
			AsyncTask<Void, Integer, Boolean> {

		private ProgressDialog progressDialog;

		private ReleaseInfo release;
		private File outputFile;

		public DownloadAppUpdateTask(Activity activity, ReleaseInfo releaseToDownload) {
			progressDialog = new ProgressDialog(activity);
			progressDialog.setMessage(getResources().getString(
					R.string.progress_appupdate_info));
			progressDialog.setIndeterminate(false);
			progressDialog.setMax(100);
			progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			
			this.release = releaseToDownload;
		}

		@Override
		protected void onPreExecute() {
			progressDialog.show();
			super.onPreExecute();
		}

		@Override
		protected Boolean doInBackground(Void... params) {
			try {
				URL apkUrl = release.getApkUrl();
				HttpURLConnection urlConnection = (HttpURLConnection) apkUrl
						.openConnection();
				urlConnection.setRequestMethod("GET");
				urlConnection.connect();

				int updateFileLength = urlConnection.getContentLength();

				outputFile = new File(
						Environment.getExternalStorageDirectory(),
						"appUpdate.apk");
				FileOutputStream fileOutputStream = new FileOutputStream(
						outputFile);
				InputStream inputStream = urlConnection.getInputStream();

				byte[] buffer = new byte[1024];
				int bufferLength = 0;
				long total = 0;

				while ((bufferLength = inputStream.read(buffer)) > 0) {
					total += bufferLength;
					publishProgress((int) (total * 100 / updateFileLength));
					fileOutputStream.write(buffer, 0, bufferLength);
				}
				fileOutputStream.flush();
				fileOutputStream.close();
				inputStream.close();

				if (outputFile.length() == updateFileLength) {
					return true;
				} else {
					return false;
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return false;
		}

		@Override
		protected void onProgressUpdate(Integer... progress) {
			progressDialog.setProgress(progress[0]);
			super.onProgressUpdate(progress);
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if (result) {
				Log.v(TAG, "Pobrano plik aktualizacji");
				progressDialog.dismiss();
				installAppUpdate(outputFile);
			}
			super.onPostExecute(result);
		}

	}
}
